#ifndef SP_JOURNAL_LOGGER_HANDLER_HPP
#define SP_JOURNAL_LOGGER_HANDLER_HPP

#include <cstdint>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <systemd/sd-journal.h>
#include <tuple>

#include "DbusContext.hpp"
#include "LogCollectionPrivate.hpp"

class JournalLoggerHandler : public DbusContext
{
public:

    static constexpr const char* SERVICE_NAME { "com.shz.JournalLoggerHandler" };
    static constexpr const char* SERVICE_PATH { "/com/shz/JournalLoggerHandler" };
    static constexpr const char* SERVICE_INTERFACE { "com.shz.JournalLoggerHandler.Interface" };

    struct JournalClient {
        pid_t mPid { -1 };
        uint64_t mStartTime { 0 };
        std::shared_ptr<LogCollector::Logger> mLogger { nullptr };

        //! 避免map赋值时失败
        //! operator[] 会 先默认构造 value(这里是 JournalClient()), 然后再赋值。
        JournalClient() = default; 

        explicit JournalClient(
            pid_t aPid, uint64_t aStartTime, std::shared_ptr<LogCollector::Logger> aLogger)
        : mPid(aPid)
        , mStartTime(aStartTime)
        , mLogger(aLogger)
        {
        }
    };
    

    explicit JournalLoggerHandler(
        const std::string& aServiceName, const std::string& aServicePath, const std::string& aServiceInterface);

    ~JournalLoggerHandler() override;

    bool prepare() override;

    bool flushAll();

    bool clearAll();

private:
    static std::string getJournalField(sd_journal* aJournal, const char* aField);

    static std::string convertRawTime(uint64_t aRawTime);

    bool registerJournalHandler();

    bool initializeJournalLoggers();

    bool addLoggerFlushTimer(LogCollector::Logger* aLogger);

    void handleLogFromJournal();

    void onJournaldReadable();

    std::optional<JournalClient> handleLogwhenClientChanged(const JournalClient& aOldClient);

    void generateLocalLog(
        std::shared_ptr<LogCollector::Logger> aLogger, pid_t aPid);

    uint64_t mStartTimestamp { 0 };

    bool mFirstEventHandled { false };

    sd_journal* mJournal { nullptr };

    sd_event_source *mTimer { nullptr };

    std::map<std::string, JournalClient> mClients;
};

#endif